package core.proto;

import java.util.*;
import static app.constants.CollabVizConstants.*;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;
import javax.swing.text.html.HTMLEditorKit;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;

import app.exceptions.CollabVizException;
import app.util.PropertyLoaderUtil;

public class NotePad extends JTextPane {

	static final long KEY_INPUT_DELAY = 1000;
	static final long SLEEP_TIME = 500;
	static final String hiliteFile;
	static final String docFile; 
	public static final String absPathKey = "abspath";

	static {
			docFile = FilenameUtils.concat(NOTEPAD_HIGHLIGHT_FOLDER, NOTEPAD_DOC_FILE);
			hiliteFile = FilenameUtils.concat(NOTEPAD_HIGHLIGHT_FOLDER, NOTEPAD_HILITE_DATA_FILE);
	}

	public NotePad() {
		File dataFileHandle = new File(docFile);
		File hiliteFileHandle = new File(hiliteFile);
		
		if (dataFileHandle.exists() && hiliteFileHandle.exists()){
			
			this.setStyledDocument((StyledDocument) Util.readObject(docFile));
			List<HiliteData> data = (List<HiliteData>) Util.readObject(hiliteFile);

			TextHighlighter hiliter =  new TextHighlighter(OPEN_FILE_NODE_FOCUS_COLOR);
			for(HiliteData d : data){ 
				try {
					getHighlighter().addHighlight(d.start, d.end, hiliter);
				} catch (BadLocationException e1) {
				}
			}
		} 
		addMouseAdapter();
		startSaveThread();
	}
	
	private String outputHtml () {
		String txt = getText();
		StringBuilder builder = new StringBuilder();
		
		for(int i = 0; i < this.getStyledDocument().getLength(); ++i){
			// TODO
		}
		return builder.toString();
	}

	private void startSaveThread () {
		final NotePad notepad = this; 
		new Thread(){
			public void run(){
				while (true) {
					try {
						String folder = NOTEPAD_HIGHLIGHT_FOLDER;
						// Write human readable version. 
						FileUtils.writeStringToFile(Util.getFile(folder, NOTEPAD_SAVE_FILE), getText ());
						// Then serialize the document model so we can restore the view next time. 
						Util.writeObject(notepad.getStyledDocument(), docFile);
						// Save the hilites too. 
						List<HiliteData> hilites = HighlightManager.getHiliteData(getHighlighter().getHighlights());
						Util.writeObject(hilites, hiliteFile);
					} catch (IOException ioe) {
						throw new Error(ioe);
					}
					try {
						Thread.sleep(SLEEP_TIME);
					} catch (InterruptedException e) {
					}
				}
			}
		}.start();
	}


	private void addMouseAdapter (){
		final NotePad notePad = this;
		this.addMouseListener(new MouseAdapter(){
			public void mouseClicked(MouseEvent me) {
				if (me.getClickCount() == 2){
					int pos = notePad.viewToModel(me.getPoint());
					AttributeSet attrs = notePad.getStyledDocument().getCharacterElement(pos).getAttributes(); 
					if (attrs.isDefined(absPathKey)){
						AllComponents.getFileTree().expandTreeByPath((String) attrs.getAttribute(absPathKey), true);
					}
				}
			}
		});
	}

	/**
	 * Use this method to import hilited text into the notepad.  
	 * @param caseAbsPath Ignored if it is null or empty string. 
	 * @param text
	 */
	public void insertText (final String caseAbsPath, String text) {
		try{
			Style style = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
			StyledDocument doc = getStyledDocument();

			doc.insertString(getCaretPosition(), "\n\n", style);
			int pos = -1;
			// Use a JLabel to represent the clickable region. 
			if (caseAbsPath != null && ! caseAbsPath.equals("")){
				// We can associate any set of attributes to particular 
				// section of the text in the JTextPane. This allows us 
				// to remember things like metadata. Here, we associate 
				// the path of the source document with the imported txt. 
				SimpleAttributeSet attrs = new SimpleAttributeSet();
				attrs.addAttribute(absPathKey, caseAbsPath);
				StyleConstants.setUnderline(attrs, true);

				// Use 1 char to represent this label. The effect is that user sees the label, but 
				// for editing purposes the label is treated as a single character.
				String caseName = FilenameUtils.getBaseName(caseAbsPath);
				pos = getCaretPosition();
				doc.insertString(getCaretPosition(), caseName, attrs);
				doc.insertString(getCaretPosition(), "\n", style);
			}
			final int start = pos == -1 ? getCaretPosition() : pos;
			doc.insertString(getCaretPosition(), text, style);
			Object tag = null;
			tag = getHighlighter().addHighlight(start, getCaretPosition(),  new TextHighlighter(OPEN_FILE_NODE_FOCUS_COLOR));
			doc.insertString(getCaretPosition(), "\n\n", style);
			// Update the highlight so it doesn't "spill over"
			getHighlighter().changeHighlight(tag, start, getCaretPosition() - 2);
		
		}catch(BadLocationException e) {

		}
	}
}
